package com.party.web.biz.crowdfund;

import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.party.common.constant.Constant;
import com.party.common.utils.DateUtils;
import com.party.common.utils.StringUtils;
import com.party.core.exception.BusinessException;
import com.party.core.model.YesNoStatus;
import com.party.core.model.activity.Activity;
import com.party.core.model.activity.ActivityDetail;
import com.party.core.model.activity.CrowfundResources;
import com.party.core.model.crowdfund.CrowdfundEvent;
import com.party.core.model.member.MemberGroup;
import com.party.core.model.member.PackageCount;
import com.party.core.model.notify.Event;
import com.party.core.model.notify.InstanceWay;
import com.party.core.model.notify.TargetTemplate;
import com.party.core.model.notify.TargetTemplateType;
import com.party.core.model.quartz.QuartzDataMap;
import com.party.core.model.system.TargetType;
import com.party.core.service.activity.IActivityDetailService;
import com.party.core.service.activity.IActivityService;
import com.party.core.service.activity.ICrowfundResourcesService;
import com.party.core.service.activity.biz.CrowfundResourceBizService;
import com.party.core.service.crowdfund.ICrowdfundEventService;
import com.party.core.service.crowdfund.IProjectService;
import com.party.core.service.crowdfund.ISupportTransferService;
import com.party.core.service.crowdfund.ITargetTemplateService;
import com.party.core.service.member.IPackageCountService;
import com.party.core.service.notify.IEventService;
import com.party.core.service.quartz.IQuartzDataMapService;
import com.party.notify.notifyPush.event.EventSendFactory;
import com.party.notify.notifyPush.event.INotifyEventSendService;
import com.party.notify.notifyPush.servce.INotifySendService;
import com.party.web.biz.activity.ActivityBizService;
import com.party.web.biz.file.FileBizService;
import com.party.web.biz.quartz.IScheduleJobService;
import com.party.web.biz.quartz.impl.SchsduleService;
import com.party.web.utils.RealmUtils;
import com.party.web.web.dto.AjaxResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 众筹项目业务接口
 * Created by wei.li
 *
 * @date 2017/7/4 0004
 * @time 11:30
 */

@Service
public class TargetBizService {

    @Autowired
    private ITargetTemplateService targetTemplateService;

    @Autowired
    private INotifySendService notifySendService;

    @Autowired
    private IActivityService activityService;

    @Autowired
    private IActivityDetailService activityDetailService;

    @Autowired
    private ICrowdfundEventService crowdfundEventService;

    @Autowired
    private EventSendFactory eventSendFactory;
    @Autowired
    private ICrowfundResourcesService crowfundResourcesService;
    @Autowired
    private CrowfundResourceBizService crowfundResourceBizService;
    @Autowired
    private FileBizService fileBizService;
    @Autowired
    private ActivityBizService activityBizService;
    @Autowired
    private IPackageCountService packageCountService;

    @Autowired
    private IScheduleJobService scheduleJobService;

    @Autowired
    private IEventService eventService;

    @Autowired
    private IQuartzDataMapService quartzDataMapService;

    @Autowired
    private IProjectService projectService;

    @Autowired
    private ISupportTransferService supportTransferService;

    Logger logger = LoggerFactory.getLogger(getClass());

    /**
     * 获取目标模板
     * @param targetId 模板编号
     * @param type 类型
     * @return 模板编号
     */
    public TargetTemplate get(String targetId, Integer type){
        type = null == type ? TargetTemplateType.CROWDFUNF_ALL.getCode() : type;
        TargetTemplate targetTemplate = targetTemplateService.findByTargetId(targetId, type);
        if (null == targetTemplate){
            targetTemplate = new TargetTemplate();
            targetTemplate.setType(type);
            targetTemplate.setTargetId(targetId);
        }
        return targetTemplate;
    }

    /**
     * 保存短信末班
     *
     * @param targetTemplate 短信模板
     */
    public String save(TargetTemplate targetTemplate){
        if (Strings.isNullOrEmpty(targetTemplate.getTemplate())){
            throw new BusinessException("模板内容不能为空");
        }
        Activity activity = activityService.get(targetTemplate.getTargetId());
        if (null == activity){
            throw new BusinessException("找不到众筹项目");
        }

        targetTemplate.setInitiatorId(activity.getMember());
        return targetTemplateService.insert(targetTemplate);
    }

    /**
     * 发送消息and保存模板
     * @param targetTemplate 目标模板
     */
    public boolean sendAndSave(TargetTemplate targetTemplate){
        if (Strings.isNullOrEmpty(targetTemplate.getTemplate())){
            throw new BusinessException("模板内容不能为空");
        }
        Activity activity = activityService.get(targetTemplate.getTargetId());
        if (null == activity){
            throw new BusinessException("找不到众筹项目");
        }

        //保存
        targetTemplate.setId(null);
        targetTemplate.setInitiatorId(activity.getMember());
        Date now = new Date();
        targetTemplate.setCreateDate(now);
        targetTemplate.setUpdateDate(now);
        targetTemplate.setSendTime(now);
        targetTemplateService.insert(targetTemplate);

        return this.crowdfundRealSend(targetTemplate, activity.getMember());
    }


    /**
     * 保存众筹模板
     * @param targetTemplate 众筹模板
     */
    public void saveForCrowdfund(TargetTemplate targetTemplate){
        if (Strings.isNullOrEmpty(targetTemplate.getTemplate())){
            throw new BusinessException("模板内容不能为空");
        }
        Activity activity = activityService.get(targetTemplate.getTargetId());
        if (null == activity){
            throw new BusinessException("找不到众筹项目");
        }

        //保存
        targetTemplate.setInitiatorId(activity.getMember());
        targetTemplateService.insert(targetTemplate);
    }


    /**
     * 发送众筹短信
     * @param id 众筹模板编号
     */
    public boolean sendForCrowdfund(String id){
        TargetTemplate targetTemplate = targetTemplateService.get(id);
        if (Strings.isNullOrEmpty(targetTemplate.getTemplate())){
            throw new BusinessException("模板内容不能为空");
        }
        Activity activity = activityService.get(targetTemplate.getTargetId());
        if (null == activity){
            throw new BusinessException("找不到众筹项目");
        }
        return this.crowdfundRealSend(targetTemplate, activity.getMember());
    }

    /**
     * 复制活动
     * @param id 活动
     */
    @Transactional
    public void copy(String id){
        MemberGroup member = RealmUtils.getCurrentUser();

        Activity activity = activityService.get(id);
        ActivityDetail activityDetail = activityDetailService.getByRefId(activity.getId());
        if (activityDetail == null) {
            activityDetail = new ActivityDetail();
        }

        // 跑马灯
        List<CrowfundResources> picList = crowfundResourcesService.findByRefId(activity.getId(), "1");
        // 视频
        List<CrowfundResources> videoList = crowfundResourcesService.findByRefId(activity.getId(), "2");

        activity.setId(null);
        activity.setCreateDate(DateUtils.getTodayDate());
        activity.setUpdateDate(DateUtils.getTodayDate());
        activity.setCreateBy(member.getId());
        activity.setUpdateBy(member.getId());

        //初始化统计数据
        activity.setBeCrowdfundNum(0);
        activity.setCrowdfundedNum(0);
        activity.setJoinNum(0);
        activity.setShareNum(0);
        activity.setReadNum(0);
        activity.setGoodNum(0);
        activity.setFavorerNum(0);
        activity.setRepresentNum(0);
        activityService.insert(activity);

        activityDetail.setId(null);
        activityDetail.setCreateDate(DateUtils.getTodayDate());
        activityDetail.setUpdateDate(DateUtils.getTodayDate());
        activityDetail.setCreateBy(member.getId());
        activityDetail.setUpdateBy(member.getId());
        activityDetail.setRefId(activity.getId());
        activityDetailService.insert(activityDetail);

        // 图片/视频
        crowfundResourceBizService.saveResourceBiz(activity.getId(), picList, videoList, activity.getMember());

        try {
            String memberId = activity.getMember();
            if (activity.getIsCrowdfunded().equals(YesNoStatus.YES.getCode())) {
                // 众筹项目

                String filePath = fileBizService.getUploadCIPath(memberId, "zcActivity");
                /*** 众筹联合发起二维码 ***/
                String dyFileName = "dy_" + activity.getId();
                String dyContent = "project/target_detail.html?id=" + activity.getId();
                fileBizService.uploadCloudOut(dyFileName, filePath, dyContent, memberId);

                /*** 众筹项目详情二维码 ***/
                String xqFileName = "detail_" + activity.getId();
                String detailContent = "project/target_client_detail.html?id=" + activity.getId();
                fileBizService.uploadCloudOut(xqFileName, filePath, detailContent, memberId);
            } else if (activity.getIsCrowdfunded().equals(YesNoStatus.NO.getCode())) {
                // 普通活动

                String filePath = fileBizService.getUploadCIPath(memberId, "activity");
                /*** 详情二维码 ***/
                String fileName = "detail_" + activity.getId();
                String content = "hd/hd_detail.html?hdId=" + activity.getId();
                fileBizService.uploadCloudOut(fileName, filePath, content, memberId);

                /*** 签到二维码 ***/
                String bmFileName = "sign_" + activity.getId();
                String bmContent = "hd/hdbm_sign.html?hdId=" + activity.getId();
                fileBizService.uploadCloudOut(bmFileName, filePath, bmContent, memberId);

                /*** 分销二维码 ***/
                String fxFileName = "fx_" + activity.getId();
                String fxContent = activityBizService.getDistributionUrl(activity.getId(), memberId);
                fileBizService.uploadCloudOut(fxFileName, filePath, fxContent, memberId);
            }
        } catch (Exception e) {
            logger.error("活动/众筹项目二维码生成异常", e);
        }
    }

    /**
     * 主题短信推送
     *
     * @param targetTemplate 模板
     * @return
     */
    public boolean sendAndSaveForEvent(TargetTemplate targetTemplate) {
        if (Strings.isNullOrEmpty(targetTemplate.getTemplate())) {
            throw new BusinessException("模板内容不能为空");
        }

        CrowdfundEvent crowdfundEvent = crowdfundEventService.get(targetTemplate.getTargetId());
        if (crowdfundEvent == null) {
            throw new BusinessException("众筹事项不存在");
        }

        targetTemplate.setId(null);
        targetTemplate.setInitiatorId(crowdfundEvent.getCreateBy());
        Date now = new Date();
        targetTemplate.setCreateDate(now);
        targetTemplate.setUpdateDate(now);
        targetTemplate.setSendTime(now);
        targetTemplateService.insert(targetTemplate);

        return this.eventRealSend(targetTemplate, crowdfundEvent.getCreateBy());
    }

    /**
     * 保存事项模板
     * @param targetTemplate 模板
     */
    public String saveForEvent(TargetTemplate targetTemplate){
        if(Strings.isNullOrEmpty(targetTemplate.getTemplate())){
            throw new BusinessException("模板内容不能为空");
        }

        CrowdfundEvent crowdfundEvent = crowdfundEventService.get(targetTemplate.getTargetId());
        if(crowdfundEvent == null){
            throw new BusinessException("众筹事项不存在");
        }
        targetTemplate.setInitiatorId(crowdfundEvent.getCreateBy());
        return targetTemplateService.insert(targetTemplate);
    }

    /**
     * 推送事项模板消息
     *
     * @param id 编号
     */
    public boolean sendForEvent(String id) {
        TargetTemplate targetTemplate = targetTemplateService.get(id);
        if (Strings.isNullOrEmpty(targetTemplate.getTemplate())) {
            throw new BusinessException("模板内容不能为空");
        }

        CrowdfundEvent crowdfundEvent = crowdfundEventService.get(targetTemplate.getTargetId());
        if (crowdfundEvent == null) {
            throw new BusinessException("众筹事项不存在");
        }
        return this.eventRealSend(targetTemplate, crowdfundEvent.getCreateBy());
    }

    /**
     * 主题短信真实发送
     *
     * @param targetTemplate 模板
     * @param orgId          机构id
     * @return
     */
    public boolean eventRealSend(TargetTemplate targetTemplate, String orgId) {
        PackageCount packageCount = packageCountService.getUnique(new PackageCount(orgId, TargetType.PUSH_SMS.getCode()));
        if (packageCount != null && YesNoStatus.YES.getCode().equals(packageCount.getIsOpen())) {
            Integer spareNum = packageCountService.getSpareNum(packageCount.getTotalNum(), packageCount.getUseNum());
            targetTemplate.setSpareNum(spareNum);
        }
        INotifyEventSendService notifyEventSendService
                = eventSendFactory.getSender(TargetTemplateType.get(targetTemplate.getType()));

        return notifyEventSendService.send(targetTemplate, targetTemplate.getTargetId(),
                orgId, InstanceWay.ORGANIZATION.getName());
    }

    /**
     * 众筹短信真实发送
     *
     * @param targetTemplate 模板
     * @param orgId          机构id
     * @return
     */
    public Boolean crowdfundRealSend(TargetTemplate targetTemplate, String orgId) {
        PackageCount packageCount = packageCountService.getUnique(new PackageCount(orgId, TargetType.PUSH_SMS.getCode()));
        if (packageCount != null && YesNoStatus.YES.getCode().equals(packageCount.getIsOpen())) {
            Integer spareNum = packageCountService.getSpareNum(packageCount.getTotalNum(), packageCount.getUseNum());
            targetTemplate.setSpareNum(spareNum);
        }
        //发送
        if (TargetTemplateType.CROWDFUNF_ALL.getCode().equals(targetTemplate.getType())) {
            return notifySendService.sendAllCrowdfund(targetTemplate.getTargetId(),
                    orgId, targetTemplate, InstanceWay.ORGANIZATION.getName());
        } else if (TargetTemplateType.CROWDFUND_UNDERWAY.getCode().equals(targetTemplate.getType())) {
            return notifySendService.sendUnderwayCordfund(targetTemplate.getTargetId(),
                    orgId, targetTemplate, InstanceWay.ORGANIZATION.getName());
        } else if (TargetTemplateType.CROWDFUND_SUCCESS.getCode().equals(targetTemplate.getType())) {
            return notifySendService.sendSuccessCrowdfund(targetTemplate.getTargetId(),
                    orgId, targetTemplate, InstanceWay.ORGANIZATION.getName());
        }
        return true;
    }

    /**
     * 消息推送-定时
     * @param targetTemplate
     * @param dateTime: 格式为yyyy-MM-dd HH:mm:ss
     * @param type: 1: 众筹项目 2: 众筹事件
     * @return
     */
    @Transactional
    public AjaxResult sendQuartz(TargetTemplate targetTemplate, String dateTime, String behavior, Integer type) {
        AjaxResult ajaxResult = new AjaxResult();
        Date date = null;
        if (StringUtils.isEmpty(dateTime)) {
            return AjaxResult.error("dateTime不能为空");
        }
        if (dateTime.indexOf(":") == dateTime.lastIndexOf(":")) {
            dateTime = dateTime + ":00";
        }
        try {
            date = DateUtils.parse(dateTime, "yyyy-MM-dd HH:mm:ss");
        } catch (ParseException e) {
            logger.error("定时推送短信失败, 时间参数有误 dateTime = {}", dateTime, e);
            ajaxResult.setDescription("定时推送短信失败, 时间参数有误 dateTime = " + dateTime);
            ajaxResult.setSuccess(false);
            return ajaxResult;
        }

        // 定时的时间小于当前时间, 则直接立即执行
        if (date.getTime() < System.currentTimeMillis()) {
            if (Constant.SEND_SHORT_MESSAGE_TYPE_Event.equals(type)) {
                if ("add".equals(behavior)) {
                    this.sendAndSaveForEvent(targetTemplate);
                } else if ("modifyTime".equals(behavior)){
                    return AjaxResult.error("时间参数有误, 该时间将永远不会执行 dateTime = " + dateTime);
                } else {
                    this.sendForEvent(targetTemplate.getId());
                }
            } else if (Constant.SEND_SHORT_MESSAGE_TYPE_CROWDFUN_PROJECT.equals(type)) {
                if ("add".equals(behavior)) {
                    this.sendAndSave(targetTemplate);
                } else if ("modifyTime".equals(behavior)){
                    return AjaxResult.error("时间参数有误, 该时间将永远不会执行 dateTime = " + dateTime);
                } else {
                    this.sendForCrowdfund(targetTemplate.getId());
                }
            }
            return AjaxResult.success();
        }

        targetTemplate.setSendTime(date);
        String tempId = null;
        boolean hasTemp;
        if ("add".equals(behavior)) {
            targetTemplate.setId(null);
            if (Constant.SEND_SHORT_MESSAGE_TYPE_CROWDFUN_PROJECT.equals(type)) {
                tempId = this.save(targetTemplate);
            } else if (Constant.SEND_SHORT_MESSAGE_TYPE_Event.equals(type)) {
                tempId = this.saveForEvent(targetTemplate);
            }
            hasTemp = false;
        } else {
            // 如果是修改发送时间, 需要检测该短信是否已经发送了
            if ("modifyTime".equals(behavior)) {
                TargetTemplate dbTemp = targetTemplateService.get(targetTemplate.getId());
                Date sendTime = dbTemp.getSendTime();
                if (null != sendTime && sendTime.getTime() < System.currentTimeMillis()) {
                    return AjaxResult.error("该短信已经发送了, 请刷新页面");
                }
            }
            targetTemplateService.update(targetTemplate);
            tempId = targetTemplate.getId();
            hasTemp = true;
        }

        if (StringUtils.isEmpty(tempId)) {
            return AjaxResult.error("保存定时发送短信模板失败, template = " + targetTemplate);
        }

        String cron = DateUtils.formatDate(date, "s m HH d M ? yyyy");

        final String clazz = "quartzBizSendShortMessage";
        final String method = "send";

        List<Object> params = Lists.newArrayList();
        params.add(type);

        Event event;
        if (hasTemp) {
            event = eventService.findByCode(clazz);
            event.setCronExpression(cron);
            scheduleJobService.dynamicUpdate(event, tempId, SchsduleService.GROUP_SEND_SHORT_MESSAGE, params);
        } else {
            event = new Event();
            event.setWay(com.party.common.constant.Constant.EVENT_AUTO);
            event.setName(SchsduleService.JOB_SEND_SHORT_MESSAGE);
            event.setCode(clazz);
            event.setType("4");
            event.setCronExpression(cron);
            event.setIsSync(0);
            event.setClassName(clazz);
            event.setMethod(method);
            scheduleJobService.dynamicInsert(event, tempId, SchsduleService.GROUP_SEND_SHORT_MESSAGE, params);
        }

        ajaxResult.setSuccess(true);
        return ajaxResult;
    }

    /**
     * 删除短信
     * @param id: 模板id
     * @return
     */
    @Transactional
    public AjaxResult delQuartz(String id) {
        if (StringUtils.isEmpty(id)) {
            return AjaxResult.error("短信模板id不能为空");
        }
        TargetTemplate targetTemplate = targetTemplateService.get(id);
        if (null == targetTemplate) {
            return AjaxResult.error("找不到对应的模板 id= " + id);
        }
        // 移除定时器
        final String triggerName = SchsduleService.JOB_SEND_SHORT_MESSAGE.concat(SchsduleService.SEND_SHORT_MESSAGE_LINE).concat(id);
        final String group = SchsduleService.GROUP_SEND_SHORT_MESSAGE;
        scheduleJobService.removeTrigger(triggerName, group);
        // 删除短信
        targetTemplateService.delete(id);
        // 删除存的值在qrtz_data_map
        final String targetId = SchsduleService.PARAMS.concat(SchsduleService.SEND_SHORT_MESSAGE_LINE).concat(id);
        QuartzDataMap quartzDataMap = quartzDataMapService.findByTargetId(targetId);
        if (null != quartzDataMap) {
            quartzDataMapService.delete(quartzDataMap.getId());
        }
        return AjaxResult.success();
    }

    /**
     * 获取众筹项目的统计数
     *
     * @param id 众筹项目id
     * @return 统计数
     */
    public Map<String, Object> getTargetData(String id) {
        Map<String, Object> map = Maps.newHashMap();

        // 众筹数、联合发起数
        Activity activity = activityService.get(id);
        map.put("activity", activity);

        // 直接付款
        Integer directPayNum = projectService.directPaySizeForTargetId(id, null, 1);
        map.put("directPayNum", directPayNum);

        // 转入
        Integer transferNum = supportTransferService.getShiftToPeopleTotal(id);
        map.put("transferNum", transferNum == null ? 0 : transferNum);

        map.put("crowdfundNum", projectService.sizeForTargetId(id));

        return map;
    }
}
